<?php

namespace System\Core;

if (!defined('BASEPATH')) die('Access Denied.');

/**
 * µMVC Framework (c) 2011.
 * 
 * PHP5 MVC Framework software for PHP 5.2.17 or later
 * 
 * @package         µMVC
 * @filename        system/core/uri.class.php
 * @copyright       Lanz (c) 2011.
 * 
 */

class UriException extends CommonException {};

/**
 * URI class
 * Fetches the URI string from the URL based on what $_SERVER or environment
 * variables that is available.
 * 
 * @package         µMVC
 * @subpackage      Core
 * @category        System
 * 
 */
class URI extends BaseSingleton
{

    /**
     * The default raw URI string.
     * @var string 
     */
    private $_uriString;
    
    /**
     * Contains the individual segments from the URI string.
     * @var array
     */
    private $_segments = array();
       
    function __construct()
    {
        $this->_fetchUriString();
        $this->_explodeSegments();
        Log::instance()->write(Log::DEBUG, 'URI Class intitialized');
    }

    /**
     * This fetches the URI from either $_GET or one of several server variables.
     * 
     * @return type 
     */
    private function _fetchUriString()
    {
       
        if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')
        {
            $this->_uriString = key($_GET);
        }

        $path = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : @getenv('REQUEST_URI');
        if (trim($path, '/') != '')
        {
            $this->_uriString = $path;
            return;
        }
        
        $path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
        if (trim($path, '/') != '' && $path != "/" . SELF)
        {
            $this->_uriString = $path;
            return;
        }

        $path = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
        if (trim($path, '/') != '')
        {
            $this->_uriString = $path;
            return;
        }

        $path = (isset($_SERVER['ORIG_PATH_INFO'])) ? $_SERVER['ORIG_PATH_INFO'] : @getenv('ORIG_PATH_INFO');
        if (trim($path, '/') != '' && $path != "/" . SELF)
        {
            $this->_uriString = str_replace($_SERVER['SCRIPT_NAME'], '', $path);
            return;
        }
        
        // We have exhausted all our options.
        $this->_uriString = '';
    }

    /**
     * Checks so that the current segment is not using any characters that is
     * forbidden for security reasons.
     * 
     * @param string $str The segment
     */
    private function _checkSegment($str)
    {
        if (!preg_match("/^[a-z 0-9~%.:_\-']+$/i", $str))
        {
            throw new UriException('The URI you submitted contains forbidden characters.');
        }  
    }
    
    private function _explodeSegments()
    {
        foreach(explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->_uriString)) as $val)
        {
            $val = trim($val);
                        
            if ($val != '')
            {
                // Check segments for security
                $this->_checkSegment($val);
                $this->_segments[] = $val;
            }
        }
        
        // Re-index the array so segments starts with 1 instead of 0.
        if (count($this->_segments) > 0)
        {
            array_unshift($this->_segments, NULL);
            unset($this->_segments[0]);
        }
    }    
    
    public function getSegment($index)
    {
        if (isset($this->_segments[$index]))
        {
            return $this->_segments[$index];
        }
        
        return FALSE;
                
    }
    
    public function getSegments()
    {
        return $this->_segments;
    }
    
    public function getUriString()
    {
        return $this->_uriString;
    }
}

?>
